package com.itheima.service.impl;

import com.itheima.common.utils.POIUtils;
import com.itheima.mapper.OrdersettingMapper;
import com.itheima.pojo.OrderSetting;
import com.itheima.service.OrdersettingService;
import com.itheima.vo.OrderSettingVO;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.YearMonth;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class OrdersettingServiceImpl implements OrdersettingService {

    @Autowired
    private OrdersettingMapper ordersettingMapper;

    /**
     * 根据年月查询对应的预约设置信息
     * @param month
     * @return
     */
    @Override
    public List<OrderSettingVO> getOrderSettingByMonth(String month) {
        // 获取年月中每月的第一天和最后一天
        String[] split = month.split("-");
        YearMonth yearMonth = YearMonth.of(Integer.valueOf(split[0]).intValue(), Integer.valueOf(split[1]).intValue());
        LocalDate beginOfMonth = LocalDate.of(yearMonth.getYear(), yearMonth.getMonth(), 1); // 每月的第一天
        LocalDate endOfMonth = yearMonth.atEndOfMonth();  // 每月的最后一天
        List<OrderSetting> orderSettingList = ordersettingMapper.getOrderSettingByMonth(beginOfMonth, endOfMonth); // 根据每月第一天和每月最后一天查询范围内的预约设置信息

        // 封装返回结果
        List<OrderSettingVO> orderSettingVOList = new ArrayList<>();
        for (OrderSetting orderSetting : orderSettingList) {
            OrderSettingVO orderSettingVO = new OrderSettingVO();
            BeanUtils.copyProperties(orderSetting, orderSettingVO); // 属性拷贝

            // 设置当前日期是每月的第几天
            String orderDate = orderSetting.getOrderDate().toString();
            String[] split1 = orderDate.split(" ");
            orderSettingVO.setDate(Integer.valueOf(split1[2]).intValue()); // 设置当前日期是每月的第几天
            orderSettingVOList.add(orderSettingVO);
        }
        return orderSettingVOList;
    }

    /**
     * 根据日期修改可预约人数
     * @param orderSetting
     */
    @Override
    public void editNumberByOrderDate(OrderSetting orderSetting) {
        System.out.println(orderSetting.getOrderDate());

        /*
        前端传入日期（2024-11-23）后，后端用Date类型接收后结果为Sat Nov 23 08:00:00 CST 2024
                                                 正确结果为Sat Nov 23 00:00:00 CST 2024
        原因：Date类型在java中不仅有日期还有时间，如果没有时间，默认时间为00:00:00（UTC时间，世界统一时间），
        而CST(中国标准时间)比UTC偏移8个小时
        解决方案一：用SimpleDateFormat将日期格式化为字符串后再解析为Date类型
        解决方案二：update t_ordersetting set number = #{number} where orderDate = date(#{orderDate})
         */
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String orderDate = simpleDateFormat.format(orderSetting.getOrderDate());
        System.out.println(orderDate);
        try {
            Date date = simpleDateFormat.parse(orderDate);
            orderSetting.setOrderDate(date);
            if (ordersettingMapper.findByOrderDate(date) != null){
                ordersettingMapper.editNumberByOrderDate(orderSetting);
            }else{
                ordersettingMapper.add(orderSetting);
            }

        } catch (ParseException e) {
            e.printStackTrace();
        }

    }

    /**
     * 模板下载
     * @param filename
     * @param response
     */
    @Override
    public void download(String filename, HttpServletResponse response) {
        /*
        this.getClass(): 获取当前类的 Class 对象。
        getClassLoader(): 获取当前类的类加载器。
        getResourceAsStream(filename): 通过类加载器从应用程序的类路径中获取指定文件的输入流。
         */
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("templates/" + filename);
        try {
            // 使用inputStream创建一个XSSWorkbook对象,该对象表示要下载的Excel文件
            XSSFWorkbook excel = new XSSFWorkbook(inputStream);
            // 获取ServletOutputStream对象，用于向客户端写入相应数据
            ServletOutputStream servletOutputStream = response.getOutputStream();
            // 设置响应的ContentType为application/octet-stream,这是一种常见的MIME类型，表示任意的二进制流
            response.setContentType("application/octet-stream");
            // 设置响应头Content-Disposition为attachment，告诉客户端将文件作为附件下载，同时设置了文件名
            response.setHeader("Content-Disposition", "attachment;fileName=" + filename);
            // 将Excel工作簿的内容写入到SercvletOutputStream中，从而将文件内容发送给客户端
            excel.write(servletOutputStream);

            // 释放资源
            excel.close();
            servletOutputStream.close();
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 文件上传
     * @param excelFile
     */
    @Override
    public void upload(MultipartFile excelFile) {
        try {
            // 调用工具类读取excel文件，解析后返回除了第一行以外的所有行
            List<String[]> list = POIUtils.readExcel(excelFile);
            if(list != null && list.size() > 0){
                // 将excel中读取到的日期和可预约人数封装到orderSetting对象中
                ArrayList<OrderSetting> orderSettings = new ArrayList<>();
                // 使用SimpleDateFormat格式化时间
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd");
                // strings[0]为日期 strings[1]为可预约人数
                for (String[] strings : list) {
                    try {
                        // 创建OrderSetting对象
                        OrderSetting orderSetting = new OrderSetting();
                        // 封装日期数据
                        orderSetting.setOrderDate(simpleDateFormat.parse(strings[0]));
                        // 封装可预约人数数据
                        orderSetting.setNumber(Integer.valueOf(strings[1]).intValue());
                        // 将OrderSetting对象加入到集合中
                        orderSettings.add(orderSetting);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }
                // 循环遍历orderSettings集合
                for (OrderSetting orderSetting : orderSettings) {
                    // 根据日期查询，如果有数据，说明是更新可预约人数操作；如果没有数据，说明是新增操作
                    if(ordersettingMapper.findByOrderDate(orderSetting.getOrderDate()) != null){
                        // 根据日期修改可预约人数
                        ordersettingMapper.editNumberByOrderDate(orderSetting);
                    }else {
                        // 新增数据
                        ordersettingMapper.add(orderSetting);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
